﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Web.UI;
using Microsoft.SharePoint;
using System.Web.UI.WebControls;

namespace arb.SharePoint.SecureSilverlight
{
    public static class Extensions
    {
        #region Content Type Extensions
        public static bool ContentTypeExists(this SPWeb web, string name)
        {
            return web.AvailableContentTypes.Cast<SPContentType>().Any(spContentType =>
                                                                       Equals(spContentType.Name, name));
        }

        public static void AddContentType(this SPList instance)
        {
            SPContentType ct = Builders.CreateContentTypeForInstanceList(instance.ParentWeb);
            if (instance.ContentTypesEnabled == false)
            {
                instance.ContentTypesEnabled = true;
            }
            if (instance.ContainsContentType(ct.Id))
            {
                return;
            }
            SPWeb web = instance.ParentWeb;
            try
            {
                if (web.ContentTypes.BestMatch(ct.Id).Parent.Equals(ct.Id) == false)
                {
                    if (!instance.ContainsContentType(ct.Id))
                    {
                        instance.ContentTypes.Add(ct);
                        instance.Update();
                    }
                }
            }
            catch (Exception e)
            {
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture,
                                                              "Failed to add contenttype id '{0}' to list '{1}' on '{2}'.",
                                                              ct.Id, instance.Title, web.Url), e);
            }
          
        }

        public static void RemoveContentType(this SPList instance, SPContentTypeId contentTypeId)
        {
            SPContentTypeId ctId = instance.ContentTypes.BestMatch(contentTypeId);
            if (ctId.Parent.Equals(contentTypeId) == false)
            {
                return;
            }

            RemoveContentType(instance, ctId, contentTypeId);
        }

        private static void RemoveContentType(SPList instance, SPContentTypeId contentTypeId, SPContentTypeId originalContentTypeId)
        {
            try
            {
                if (contentTypeId.Parent.Equals(originalContentTypeId))
                {
                    instance.ContentTypes.Delete(contentTypeId);
                    instance.Update();
                }
                else
                {
                    if (contentTypeId.Parent.Equals(contentTypeId) == false)
                    {
                        RemoveContentType(instance, contentTypeId.Parent, originalContentTypeId);
                    }
                    return;
                }
            }
            catch (Exception e)
            {
                throw new NotSupportedException(string.Format(CultureInfo.InvariantCulture,
                                                              "Failed to remove contenttype id '{0}' from list '{1}' on '{2}'.",
                                                              contentTypeId.ToString(), instance.Title, instance.ParentWeb.Url), e);
            }
        }

        public static bool ContainsContentType(this SPList instance, SPContentTypeId contentTypeId)
        {
            SPContentTypeId bm = instance.ContentTypes.BestMatch(contentTypeId);
            bool contains = bm.Equals(contentTypeId);
            return contains;
        } 
        #endregion

        #region Security Extensions
        public static void AddGroupCheckEvent(this SPContentType ct, string eventName)
        {
            string assemblyNameFull = System.Reflection.Assembly.GetExecutingAssembly().FullName;
            string assemblyNameShortend = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
            string ctReceiverName = assemblyNameShortend + eventName;
            ct.EventReceivers.Add(SPEventReceiverType.ItemAdding, assemblyNameFull, ctReceiverName);
            ct.Update();
        }

        public static bool IsMemberOfGroup(this SPUser user, string groupName)
        {
            return user.Groups.Cast<SPGroup>().Any(g => g.Name.ToLower() == groupName.ToLower());
        }

        public static SPGroup GetOrCreateGroup(this SPWeb web, string groupName,
                                       Func<SPWeb, string, SPGroup> groupBuilder,
                                       Action<SPWeb, SPGroup> associateGroup)
        {
            SPGroup group = web.SiteGroups.Cast<SPGroup>()
                                .FirstOrDefault(g =>
                                    string.Equals(g.Name, groupName,
                                        StringComparison.OrdinalIgnoreCase));
            if (group == null && groupBuilder != null)
            {
                group = groupBuilder(web, groupName);
            }
            if (group != null && associateGroup != null)
            {
                associateGroup(web, group);
            }
            return group;
        }

     

        #endregion

        #region List And Item Extensions
        public static bool ListExists(this SPWeb web, string listName)
        {
            return web.Lists.Cast<SPList>().Any(list => string.Compare(list.Title, listName, true) == 0);
        }

        public static T GetSafeValue<T>(this SPListItem item, string fieldName) where T : class
        {
            var o = item[fieldName];
            if (o == null || !(o is T))
            {
                return null;
            }
            return (T)o;
        }

        public static string GetFieldValueUserLogin(this SPListItem item, string fieldName)
        {
            if (item != null)
            {
                var userValue = new SPFieldUserValue(item.Web, item[fieldName] as string);
                if (userValue.User != null)
                {
                    return userValue.User.LoginName;
                }
            }
            return string.Empty;
        }

        public static T? GetSafeValueNulled<T>(this SPListItem item, string fieldName) where T : struct
        {
            var o = item[fieldName];
            if (o == null || !(o is T))
            {
                return null;
            }
            return (T)o;
        }

        public static string GetFieldValueUrl(this SPListItem item, string fieldName)
        {
            return new SPFieldUrlValue(item[fieldName] as string).Url;
        }

        public static void SetFieldValueUrl(this SPListItem item, string fieldName, string url, string description)
        {
            item[fieldName] = new SPFieldUrlValue { Description = description, Url = url };
        }
        public static List<SPDocumentLibrary> GetAllNonSystemDocLibs(this SPWeb web)
        {
            return (web.Lists.Cast<SPList>().Where(list => list.BaseType == SPBaseType.DocumentLibrary && list.BaseTemplate == SPListTemplateType.DocumentLibrary &&
                                                           !list.Hidden).Where(list => list.Title != "Style Library" && list.Title != "Site Collection Images")).
                    Cast<SPDocumentLibrary>().ToList();
        }

        #endregion

        #region Interface Extensions
        public static void InsertBreak(this Panel panel)
        {
            panel.Controls.Add(new LiteralControl("<br><br>"));
        }
        #endregion
    }
}